/*
 * Copyright (c) 2006-2021, Halo team
 *
 * SPDX-License-Identifier: GPLv3
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-09-11     Eywen        the first version
 */

#include "heater.h"
#include <rtthread.h>

static bool heater_init(heater_t *heater, int pin_heater, bool heater_level,
                        uint32_t time_interval,
                   temperature_t *temperature_sensor);
static void heater_schedule_start(heater_t *heater);
static void heater_schedule_stop(heater_t *heater);
static void heater_schedule_task(void *parameter);
static void heater_target_set(heater_t *heater, float target);
static float heater_target_get(heater_t *heater);

const static heater_ops_t s_heater_ops = {
    .init  = heater_init,
    .start = heater_schedule_start,
    .stop  = heater_schedule_stop,
    .schedule_task = heater_schedule_task,
    .target_set = heater_target_set,
    .target = heater_target_get,
};

bool heater_register(heater_t *heater)
{
    ASSERT_NULL(heater);

    MEM_MEMSET(heater, 0, sizeof (heater_t));
    heater->ops = &s_heater_ops;

    return true;
}

/* 加热器的定时器会定时调用这个函数 */
void heater_schedule_task(void *parameter)
{
    debug_info("time out");
    return ;
    heater_t *heater;
    heater = (heater_t *)parameter;
    ASSERT_NULL(heater);
    ASSERT_NULL(heater->ops);
    ASSERT_NULL(heater->temperature);
    ASSERT_NULL(heater->pid);
    ASSERT_NULL(heater->pid->ops);
    ASSERT_NULL(heater->pid->ops->run_once);

    float temp;
    float heater_value;
    temperature_t *tem_sensor;
    pid_control_t *pid;

    pid = heater->pid;
    tem_sensor = heater->temperature;

    /* 获取当前温度 */
    temp = tem_sensor->ops->temperature_get(tem_sensor);

    /* 计算pid的输出 */
    heater_value = pid->ops->run_once(pid, temp);

    debug_info("heater ntc temperature: %d output: %d", (int)temp, (int)heater_value);
}


/* 初始化加热器 */
bool heater_init(heater_t *heater, int pin_heater, bool heater_level,
                 uint32_t time_interval,
                 temperature_t *temperature_sensor)
{
    ASSERT_NULL(heater);
    ASSERT_NULL(temperature_sensor);
    ASSERT_NULL(heater->ops);
    ASSERT_NULL(heater->ops->schedule_task);

    heater->pin_heater = pin_heater;
    heater->heater_level = heater_level;
    heater->temperature = temperature_sensor;

    heater->timer = rt_timer_create("heater", heater->ops->schedule_task,
                                    heater, time_interval*1000/RT_TICK_PER_SECOND,
                                    RT_TIMER_FLAG_PERIODIC);

    if(NULL == heater->timer){
        debug_error("Timer creation failed");
        return false;
    }

    debug_info("heater init ok");
    return true;
}

/* 打开加热器调度定时器 */
void heater_schedule_start(heater_t *heater)
{
    ASSERT_NULL(heater);
    ASSERT_NULL(heater->timer);

    rt_timer_start(heater->timer);
}

/* 停止加热器调度定时器 */
void heater_schedule_stop(heater_t *heater)
{
    ASSERT_NULL(heater);
    ASSERT_NULL(heater->timer);

    rt_timer_stop(heater->timer);
}

/* 创建一个加热器 */
heater_t *heater_create(pid_type_t pid_type)
{
    heater_t *heater;

    heater = MEM_MALLOC(sizeof (heater_t));
    if(NULL == heater){
        debug_error("Insufficient system memory");
        goto err;
    }

    if(false == heater_register(heater)){
        debug_error("heater register fail");
        goto err;
    }

    pid_control_t *pid;
    pid = pid_control_create(pid_type);
    if(NULL == pid){
        debug_error("pid crater fail");
        goto err;
    }

    heater->pid = pid;

    debug_info("heater creater success");
    return heater;
err:
    debug_error("heater creater fail");
    if(NULL != heater){
        if(NULL != heater->pid){
            MEM_FREE(heater->pid);
        }
        MEM_FREE(heater);
    }
    return NULL;
}

/* 设置加热器的目标值 */
void heater_target_set(heater_t *heater, float target)
{
    ASSERT_NULL(heater);

    heater->pid->ops->target_set(heater->pid, target);
}

/* 返回加热器的目标值 */
float heater_target_get(heater_t *heater)
{
    ASSERT_NULL(heater);

    return heater->pid->ops->target(heater->pid);
}

